home *** CD-ROM | disk | FTP | other *** search
/ Aminet 33 / Aminet 33 - October 1999.iso / Aminet / dev / cross / avra-0.4_src.lha / avra-0.4 / macro.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-03-24  |  7.3 KB  |  269 lines

  1. /***********************************************************************
  2.  *  avra - Assembler for the Atmel AVR microcontroller series
  3.  *  Copyright (C) 1998-1999 Jon Anders Haugum
  4.  *
  5.  *  This program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2 of the License, or
  8.  *  (at your option) any later version.
  9.  *
  10.  *  This program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  *  GNU General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with this program; see the file COPYING.  If not, write to
  17.  *  the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  18.  *  Boston, MA 02111-1307, USA.
  19.  *
  20.  *
  21.  *  Author of avra can be reached at:
  22.  *     email: jonah@omegav.ntnu.no
  23.  *     www: http://www.omegav.ntnu.no/~jonah/el/avra.html
  24.  */
  25.  
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include <string.h>
  29. #include <ctype.h>
  30.  
  31. #include "misc.h"
  32. #include "args.h"
  33. #include "avra.h"
  34.  
  35. int read_macro(struct prog_info *pi, char *name, int pass)
  36.     {
  37.     int loopok, i;
  38.     struct macro *macro;
  39.     struct macro_line *macro_line, **last_macro_line;
  40.  
  41.     if(pass == PASS_1)
  42.         {
  43.         if(!name)
  44.             {
  45.             print_msg(pi, MSGTYPE_ERROR, "Missing macro name");
  46.             return(True);
  47.             }
  48.         get_next_token(name, TERM_END);
  49.         // TODO: Sjekk om navnet er gyldig. Bare isalnum() og '_'
  50.         macro = calloc(1, sizeof(struct macro));
  51.         if(!macro)
  52.             {
  53.             print_msg(pi, MSGTYPE_OUT_OF_MEM, NULL);
  54.             return(False);
  55.             }
  56.         if(pi->last_macro)
  57.             pi->last_macro->next = macro;
  58.         else
  59.             pi->first_macro = macro;
  60.         pi->last_macro = macro;
  61.         macro->name = malloc(strlen(name) + 1);
  62.         if(!macro->name)
  63.             {
  64.             print_msg(pi, MSGTYPE_OUT_OF_MEM, NULL);
  65.             return(False);
  66.             }
  67.         strcpy(macro->name, name);
  68.         macro->include_file = pi->fi->include_file;
  69.         macro->first_line_number = pi->fi->line_number;
  70.         last_macro_line = ¯o->first_macro_line;
  71.         }
  72.     else if(pi->list_line && pi->list_on) /* pass == PASS_2 */
  73.         {
  74.         fprintf(pi->list_file, "          %s", pi->list_line);
  75.         pi->list_line = NULL;
  76.         }
  77.     loopok = True;
  78.     while(loopok)
  79.         {
  80.         if(fgets(pi->fi->buff, LINEBUFFER_LENGTH, pi->fi->fp))
  81.             {
  82.             pi->fi->line_number++;
  83.             i = 0;
  84.             while(IS_HOR_SPACE(pi->fi->buff[i]) && !IS_END(pi->fi->buff[i])) i++;
  85.             if(pi->fi->buff[i] == '.')
  86.                 {
  87.                 i++;
  88.                 if(!nocase_strncmp(&pi->fi->buff[i], "endm", 4)) // TODO: Vurder å sjekke navnet bedre
  89.                     loopok = False;
  90.                 }
  91.             if(pass == PASS_1)
  92.                 {
  93.                 if(loopok)
  94.                     {
  95.                     macro_line = calloc(1, sizeof(struct macro_line));
  96.                     if(!macro_line)
  97.                         {
  98.                         print_msg(pi, MSGTYPE_OUT_OF_MEM, NULL);
  99.                         return(False);
  100.                         }
  101.                     *last_macro_line = macro_line;
  102.                     last_macro_line = ¯o_line->next;
  103.                     macro_line->line = malloc(strlen(pi->fi->buff) + 1);
  104.                     if(!macro_line->line)
  105.                         {
  106.                         print_msg(pi, MSGTYPE_OUT_OF_MEM, NULL);
  107.                         return(False);
  108.                         }
  109.                     strcpy(macro_line->line, pi->fi->buff);
  110.                     }
  111.                 }
  112.             else if(pi->fi->buff && pi->list_file)
  113.                 {
  114.                 if(pi->fi->buff[i] == ';')
  115.                     fprintf(pi->list_file, "         %s", pi->fi->buff);
  116.                 else
  117.                     fprintf(pi->list_file, "          %s", pi->fi->buff);
  118.                 }
  119.             }
  120.         else
  121.             {
  122.             if(feof(pi->fi->fp))
  123.                 {
  124.                 print_msg(pi, MSGTYPE_ERROR, "Found no closing .ENDMACRO");
  125.                 return(True);
  126.                 }
  127.             else
  128.                 {
  129.                 perror(pi->fi->include_file->name);
  130.                 return(False);
  131.                 }
  132.             }
  133.         }
  134.     return(True);
  135.     }
  136.  
  137.  
  138. struct macro *get_macro(struct prog_info *pi, char *name)
  139.     {
  140.     struct macro *macro;
  141.  
  142.     for(macro = pi->first_macro; macro; macro = macro->next)    
  143.         if(!nocase_strcmp(macro->name, name))
  144.             return(macro);
  145.     return(NULL);
  146.     }
  147.  
  148.  
  149. int expand_macro(struct prog_info *pi, struct macro *macro, char *rest_line, int pass)
  150.     {
  151.     int ok = True, macro_arg_count = 0, i, j;
  152.     char *line, *temp, *macro_args[10];
  153.     char buff[LINEBUFFER_LENGTH];
  154.     struct macro_line *old_macro_line;
  155.     struct macro_call *macro_call;
  156.  
  157.     if(rest_line)
  158.         {
  159.         line = malloc(strlen(rest_line) + 1);
  160.         if(!line)
  161.             {
  162.             print_msg(pi, MSGTYPE_OUT_OF_MEM, NULL);
  163.             return(False);
  164.             }
  165.         strcpy(line, rest_line);
  166.         temp = line;
  167.         while(temp)
  168.             {
  169.             macro_args[macro_arg_count++] = temp;
  170.             temp = get_next_token(temp, TERM_COMMA);
  171.             }
  172.         }
  173.  
  174.     if(pass == PASS_1)
  175.         {
  176.         macro_call = calloc(1, sizeof(struct macro_call));
  177.         if(!macro_call)
  178.             {
  179.             print_msg(pi, MSGTYPE_OUT_OF_MEM, NULL);
  180.             return(False);
  181.             }
  182.         if(pi->last_macro_call)
  183.             pi->last_macro_call->next = macro_call;
  184.         else
  185.             pi->first_macro_call = macro_call;
  186.         pi->last_macro_call = macro_call;
  187.         macro_call->line_number = pi->fi->line_number;
  188.         macro_call->include_file = pi->fi->include_file;
  189.         macro_call->macro = macro;
  190.         macro_call->prev_on_stack = pi->macro_call;
  191.         if(macro_call->prev_on_stack)
  192.             {
  193.             macro_call->nest_level = macro_call->prev_on_stack->nest_level + 1;
  194.             macro_call->prev_line_index = macro_call->prev_on_stack->line_index;
  195.             }
  196.         }
  197.     else
  198.         {
  199.         for(macro_call = pi->first_macro_call; macro_call; macro_call = macro_call->next)
  200.             {
  201.             if((macro_call->include_file->num == pi->fi->include_file->num)
  202.                && (macro_call->line_number == pi->fi->line_number))
  203.                 {
  204.                 if(pi->macro_call)
  205.                     {
  206.                     /* Find correct macro_call when using recursion and nesting */
  207.                     if(macro_call->prev_on_stack == pi->macro_call)
  208.                         if((macro_call->nest_level == (pi->macro_call->nest_level + 1))
  209.                            && (macro_call->prev_line_index == pi->macro_call->line_index))
  210.                             break;
  211.                     }
  212.                 else
  213.                     break;
  214.                 }
  215.             }
  216.         if(pi->list_line && pi->list_on)
  217.             {
  218.             fprintf(pi->list_file, "%06x   +  %s", pi->cseg_addr, pi->list_line);
  219.             pi->list_line = NULL;
  220.             }
  221.         }
  222.     macro_call->line_index = 0;
  223.     pi->macro_call = macro_call;
  224.     old_macro_line = pi->macro_line;
  225.     for(pi->macro_line = macro->first_macro_line; pi->macro_line && ok; pi->macro_line = pi->macro_line->next)
  226.         {
  227.         macro_call->line_index++;
  228.         if(GET_ARG(pi->args, ARG_LISTMAC))
  229.             pi->list_line = buff;
  230.         else
  231.             pi->list_line = NULL;
  232.         for(i = 0, j = 0; pi->macro_line->line[i] != '\0'; i++)
  233.             {
  234.             if(pi->macro_line->line[i] == '@')
  235.                 {
  236.                 i++;
  237.                 if(!isdigit(pi->macro_line->line[i]))
  238.                     print_msg(pi, MSGTYPE_ERROR, "@ must be followed by a number");
  239.                 else if((pi->macro_line->line[i] - '0') >= macro_arg_count)
  240.                     print_msg(pi, MSGTYPE_ERROR, "Missing macro argument (for @%c)", pi->macro_line->line[i]);
  241.                 else
  242.                     {
  243.                     strcpy(&buff[j], macro_args[pi->macro_line->line[i] - '0']);
  244.                     j += strlen(macro_args[pi->macro_line->line[i] - '0']);
  245.                     }
  246.                 }
  247.             else
  248.                 buff[j++] = pi->macro_line->line[i];
  249.             }
  250.         buff[j] = '\0';
  251.         ok = parse_line(pi, buff, pass);
  252.         if(ok)
  253.             {
  254.             if((pass == PASS_2) && pi->list_line && pi->list_on)
  255.                 fprintf(pi->list_file, "         %s", pi->list_line);
  256.             if(pi->error_count >= pi->max_errors)
  257.                 {
  258.                 print_msg(pi, MSGTYPE_MESSAGE, "Maximum error count reached. Exiting...");
  259.                 break;
  260.                 }
  261.             }
  262.         }
  263.     pi->macro_line = old_macro_line;
  264.     pi->macro_call = macro_call->prev_on_stack;
  265.     if(rest_line)
  266.             free(line);
  267.     return(ok);
  268.     }
  269.